home *** CD-ROM | disk | FTP | other *** search
- #include "wand_head.h"
-
- #define viable(x,y) (((screen[y][x] == ' ') || (screen[y][x] == ':') ||\
- (screen[y][x] == '@') || (screen[y][x] == '+')) && (y >= 0) &&\
- (x >= 0) && (y < NOOFROWS) && (x < ROWLEN))
-
- /* typedef struct mon_rec *//* M002 struct mon_rec moved */
- /* { *//* to header file because it */
- /* int x,y,mx,my; *//* is needed by save.c */
- /* char under; */
- /* struct mon_rec *next,*prev; */
- /* }; */
-
- typedef struct { int d[2] } direction;
-
- #ifdef LINT_ARGS /* M001 */
- direction new_direction(int, int, int, int);
- #else
- direction new_direction();
- #endif
-
- extern int jumpscreen();
-
- extern int check();
-
- extern void showpass();
-
- extern void draw_symbol();
-
- extern void display();
-
- extern int fall();
-
- extern void map();
-
- extern int debug_disp;
- extern int edit_mode;
- extern int saved_game;
- extern char screen[NOOFROWS][ROWLEN+1];
-
- /* Add a spirit to the chain */
- /* Maintain a doubly linked list to make reuse possible.
- tail_of_list is *NOT* the last monster allocated, but
- the last monster alloted to a screen. start_of_list
- is a dummy entry to ease processing. last_of_list
- is the last entry allocated. */
- static struct mon_rec start_of_list = {0,0,0,0,0,NULL,NULL};
-
- struct mon_rec *tail_of_list;
- struct mon_rec *last_of_list;
-
- struct mon_rec *make_monster(x,y)
- int x,y;
- {
- char *malloc();
- #define MALLOC (struct mon_rec *)malloc(sizeof(struct mon_rec))
- struct mon_rec *monster;
- if(tail_of_list->next == NULL)
- {
- if((last_of_list = MALLOC) == NULL)
- return NULL;
- tail_of_list->next = last_of_list;
- last_of_list->prev = tail_of_list;
- last_of_list->next = NULL;
- }
- monster = tail_of_list = tail_of_list->next;
- monster->x = x;
- monster->y = y;
- monster->mx = 1; /* always start moving RIGHT. (fix later) */
- monster->my = 0;
- monster->under = ' ';
- return monster;
- }
-
- /* 'follow lefthand wall' algorithm for baby monsters */
-
- direction new_direction(x,y,bx,by)
- int x,y,bx,by;
- {
- direction out;
- if(viable((x+by),(y-bx)))
- {
- out.d[0] = by;
- out.d[1] = -bx;
- return out;
- }
- if(viable((x+bx),(y+by)))
- {
- out.d[0] = bx;
- out.d[1] = by;
- return out;
- }
- if(viable((x-by),(y+bx)))
- {
- out.d[0] = -by;
- out.d[1] = bx;
- return out;
- }
- if(viable((x-bx),(y-by)))
- {
- out.d[0] = -bx;
- out.d[1] = -by;
- return out;
- }
- out.d[0] = -bx;
- out.d[1] = -by;
- return out;
- }
-
- /* Actual game function - Calls fall() to move
- boulders and arrows recursively */
- /* Variable explaination :
- All the var names make sense to ME, but some people think them a bit confusing... :-) So heres an explanation.
- x,y : where you are
- nx,ny : where you're trying to move to
- sx,sy : where the screen window on the playing area is
- mx,my : where the monster is
- tx,ty : teleport arrival
- bx,by : baby monster position
- nbx,nby : where it wants to be
- lx,ly : the place you left when teleporting
- nf : how many diamonds youve got so far
- new_disp : the vector the baby monster is trying
- */
-
- char *playscreen(num,score,bell,maxmoves,keys)
- int *num, maxmoves,
- *bell,
- *score;
- char keys[10];
- {
- int x,y,nx,ny,deadyet =0,
- sx = -1,sy = -1,tx = -1,ty = -1,lx = 0,ly = 0,mx = -1,my = -1,
- bx, by, nbx, nby,
- newnum,
- max_score = 250,
- diamonds = 0, nf = 0,hd ,vd ,xdirection,ydirection;
- char (*frow)[ROWLEN+1] = screen,
- ch,
- buffer[25];
- static char howdead[25]; /* M001 can't use auto var for return value */
- direction new_disp;
- struct mon_rec *monster,*current;
-
- tail_of_list = &start_of_list;
-
- for(x=0;x<=ROWLEN;x++)
- for(y=0;y<NOOFROWS;y++)
- {
- if((screen[y][x] == '*')||(screen[y][x] == '+'))
- {
- diamonds++;
- max_score += 10;
- if(screen[y][x] == '+')
- max_score += 20;
- }
- if(screen[y][x] == 'A') /* note teleport arrival point & */
- { /* replace with space */
- tx = x;
- ty = y;
- screen[y][x] = ' ';
- }
- if(screen[y][x] == '@')
- {
- sx = x;
- sy = y;
- }
- if(screen[y][x] == 'M') /* Put megamonster in */
- {
- mx = x;
- my = y;
- }
- if(screen[y][x] == 'S') /* link small monster to pointer chain */
- {
- if((monster = make_monster(x,y)) == NULL)
- {
- strcpy(howdead,"running out of memory");
- return howdead;
- }
- if(!viable(x,y-1)) /* make sure its running in the correct */
- { /* direction.. */
- monster->mx = 1;
- monster->my = 0;
- }
- else if(!viable(x+1,y))
- {
- monster->mx = 0;
- monster->my = 1;
- }
- else if(!viable(x,y+1))
- {
- monster->mx = -1;
- monster->my = 0;
- }
- else if(!viable(x-1,y))
- {
- monster->mx = 0;
- monster->my = -1;
- }
- }
- if(screen[y][x] == '-')
- screen[y][x] = ' ';
- };
- x=sx;
- y=sy;
- if((x == -1)&&(y == -1)) /* no start position in screen ? */
- {
- strcpy(howdead,"a screen design error");
- return(howdead);
- }
-
- update_game: /* M002 restored game restarts here */
-
- move(0,48);
- (void) addstr("Score\t Diamonds");
- move(1,48);
- (void) addstr("\tFound\tTotal");
- move(3,48);
- (void) sprintf(buffer,"%d\t %d\t %d ",*score,nf,diamonds);
- (void) addstr(buffer);
- move(6,48);
- (void) sprintf(buffer,"Current screen %d",*num);
- (void) addstr(buffer);
- if(maxmoves != 0)
- (void) sprintf(buffer,"Moves remaining = %d ",maxmoves);
- else
- {
- (void) strcpy(buffer," Unlimited moves ");
- maxmoves = -1;
- };
- move(15,48);
- (void) addstr(buffer);
- if(mx != -1) /* tell player if monster exists */
- draw_symbol(48,10,'M');
- else
- draw_symbol(48,10,' ');
-
- if(!debug_disp)
- display(sx,sy,frow,*score);
- else
- map(frow);
-
- /* ACTUAL GAME FUNCTION - Returns method of death in string */
-
- while(deadyet == 0)
- {
- ch = getch();
-
- nx=x;
- ny=y;
-
- if(ch == keys[3]) /* move about - but thats obvious */
- nx++;
- if(ch == keys[2])
- nx--;
- if((ch == keys[1]) && (y<(NOOFROWS-1)))
- ny++;
- if(ch == keys[0])
- ny--;
- if(ch == '1') /* Add or get rid of that awful sound */
- {
- move(10,45);
- *bell = 1;
- (void) addstr("Bell ON ");
- move(16,0);
- refresh();
- continue;
- }
- if(ch == '0')
- {
- *bell = 0;
- move(10,45);
- (void) addstr("Bell OFF");
- move(16,0);
- refresh();
- continue;
- }
- if(ch == '~') /* level jump */
- {
- if((newnum = jumpscreen(*num)) == 0)
- {
- strcpy(howdead,"a jump error.");
- return howdead;
- }
- if(newnum != *num)
- { /* Sorry Greg, no points for free */
- sprintf(howdead,"~%c",newnum);
- return howdead;
- }
- continue;
- }
- if(ch == '!') /* look at the map */
- {
- if(debug_disp)
- continue;
- map(frow);
- display(sx,sy,frow,*score);
- continue;
- }
- if(ch == 'q')
- {
- strcpy(howdead,"quitting the game");
- return howdead;
- }
- if(ch == '?')
- {
- helpme();
- display(sx,sy,frow,*score);
- continue;
- }
-
- /* M002 Added save/restore game feature. Gregory H. Margo */
- if(ch == 'S') /* save game */
- {
- extern struct save_vars zz;
-
- /* stuff away important local variables to be saved */
- /* so the game state may be acurately restored */
- zz.z_x = x;
- zz.z_y = y;
- zz.z_nx = nx;
- zz.z_ny = ny;
- zz.z_sx = sx;
- zz.z_sy = sy;
- zz.z_tx = tx;
- zz.z_ty = ty;
- zz.z_lx = lx;
- zz.z_ly = ly;
- zz.z_mx = mx;
- zz.z_my = my;
- zz.z_bx = bx;
- zz.z_by = by;
- zz.z_nbx = nbx;
- zz.z_nby = nby;
- zz.z_max_score = max_score;
- zz.z_diamonds = diamonds;
- zz.z_nf = nf;
- zz.z_hd = hd;
- zz.z_vd = vd;
- zz.z_xdirection = xdirection;
- zz.z_ydirection = ydirection;
-
- save_game(*num, score, bell, maxmoves, &start_of_list, tail_of_list);
- /* NOTREACHED */
- }
- if(ch == 'R') /* restore game */
- {
- extern struct save_vars zz;
-
- restore_game(num, score, bell, &maxmoves, &start_of_list, &tail_of_list);
-
- /* recover important local variables */
- x = zz.z_x;
- y = zz.z_y;
- nx = zz.z_nx;
- ny = zz.z_ny;
- sx = zz.z_sx;
- sy = zz.z_sy;
- tx = zz.z_tx;
- ty = zz.z_ty;
- lx = zz.z_lx;
- ly = zz.z_ly;
- mx = zz.z_mx;
- my = zz.z_my;
- bx = zz.z_bx;
- by = zz.z_by;
- nbx = zz.z_nbx;
- nby = zz.z_nby;
- max_score = zz.z_max_score;
- diamonds = zz.z_diamonds;
- nf = zz.z_nf;
- hd = zz.z_hd;
- vd = zz.z_vd;
- xdirection = zz.z_xdirection;
- ydirection = zz.z_ydirection;
-
- if (maxmoves == -1)
- maxmoves = 0; /* to get the "unlimited moves" message */
-
- goto update_game; /* the dreaded goto */
- }
-
- if(screen[ny][nx] == 'C')
- {
- screen[ny][nx] = ':';
- *score+=4;
- if(maxmoves != -1)
- maxmoves+=250;
- }
- switch(screen[ny][nx])
- {
- case '@': break;
- case '*': *score+=9;
- max_score -= 10;
- nf++;
- case ':': *score+=1;
- move(3,48);
- sprintf(buffer,"%d\t %d",*score,nf);
- (void) addstr(buffer);
- case ' ':
- screen[y][x] = ' ';
- screen[ny][nx] = '@';
- if(!debug_disp)
- {
- draw_symbol((x-sx+5)*3,(y-sy+3)*2,' ');
- draw_symbol((nx-sx+5)*3,(ny-sy+3)*2,'@');
- }
- else
- {
- move(y+1,x+1);
- addch(' ');
- move(ny+1,nx+1);
- addch('@');
- }
- deadyet += check(&mx,&my,x,y,nx-x,ny-y,sx,sy,howdead);
- move(16,0);
- refresh();
- y = ny;
- x = nx;
- break;
- case 'O':
- if(screen[y][nx*2-x] == 'M')
- {
- screen[y][nx*2-x] = ' ';
- mx = my = -1;
- *score+=100;
- move(3,48);
- sprintf(buffer,"%d\t %d\t %d ",*score,nf,diamonds);
- (void) addstr(buffer);
- draw_symbol(48,10,' ');
- move(16,0);
- refresh();
- }
- if(screen[y][nx*2-x] == ' ')
- {
- screen[y][nx*2-x] = 'O';
- screen[y][x] = ' ';
- screen[ny][nx] = '@';
- if(!debug_disp)
- {
- draw_symbol((x-sx+5)*3,(y-sy+3)*2,' ');
- draw_symbol((nx-sx+5)*3,(ny-sy+3)*2,'@');
- if(nx*2-x>sx-6&&nx*2-x<sx+6)
- draw_symbol((nx*2-x-sx+5)*3,(y-sy+3)*2,'O');
- }
- else
- {
- move(y+1,x+1);
- addch(' ');
- move(ny+1,nx+1);
- addch('@');
- move(y+1,nx*2-x+1);
- addch('O');
- }
- deadyet += fall(&mx,&my,nx*2-x,y+1,sx,sy,howdead);
- deadyet += fall(&mx,&my,x*2-nx,y,sx,sy,howdead);
- deadyet += fall(&mx,&my,x,y,sx,sy,howdead);
- deadyet += fall(&mx,&my,x,y-1,sx,sy,howdead);
- deadyet += fall(&mx,&my,x,y+1,sx,sy,howdead);
- move(16,0);
- refresh();
- y = ny;
- x = nx;
- }
- break;
- case '<':
- case '>':
- if(screen[ny*2-y][x] == 'M')
- {
- screen[ny*2-y][x] = ' ';
- mx = my = -1;
- *score+=100;
- move(3,48);
- sprintf(buffer,"%d\t %d\t %d ",*score,nf,diamonds);
- (void) addstr(buffer);
- draw_symbol(48,10,' ');
- move(16,0);
- refresh();
- }
- if(screen[ny*2-y][x] == ' ')
- {
- screen[ny*2-y][x] = screen[ny][nx];
- screen[y][x] = ' ';
- screen[ny][nx] = '@';
- if(!debug_disp)
- {
- draw_symbol((x-sx+5)*3,(y-sy+3)*2,' ');
- draw_symbol((nx-sx+5)*3,(ny-sy+3)*2,'@');
- if(ny*2-y>sy-4&&ny*2-y<sy+4)
- draw_symbol((x-sx+5)*3,(ny*2-y-sy+3)*2,screen[ny*2-y][x]);
- }
- else
- {
- move(y+1,x+1);
- addch(' ');
- move(ny+1,nx+1);
- addch('@');
- move(ny*2-y+1,x+1);
- addch(screen[ny*2-y][x]);
- }
- deadyet += fall(&mx,&my,x,y,sx,sy,howdead);
- deadyet += fall(&mx,&my,x-1,(ny>y)?y:(y-1),sx,sy,howdead);
- deadyet += fall(&mx,&my,x+1,(ny>y)?y:(y-1),sx,sy,howdead);
- deadyet += fall(&mx,&my,x-1,ny*2-y,sx,sy,howdead);
- deadyet += fall(&mx,&my,x+1,ny*2-y,sx,sy,howdead);
- move(16,0);
- refresh();
- y = ny;
- x = nx;
- }
- break;
- case '!':
- strcpy(howdead,"an exploding landmine");
- deadyet = 1;
- if(!debug_disp)
- {
- draw_symbol((x-sx+5)*3,(y-sy+3)*2,' ');
- draw_symbol((nx-sx+5)*3,(ny-sy+3)*2,'@');
- }
- else
- {
- move(y+1,x+1);
- addch(' ');
- move(ny+1,nx+1);
- addch('@');
- }
- move(16,0);
- refresh();
- break;
- case 'X':
- if(nf == diamonds)
- {
- *score+=250;
- showpass(*num);
- return NULL;
- }
- break;
- case 'T':
- if(tx > -1)
- {
- screen[ny][nx] = ' ';
- screen[y][x] = ' ';
- lx = x;
- ly = y;
- y = ty;
- x = tx;
- screen[y][x] = '@';
- sx = x;
- sy = y;
- *score += 20;
- move(3,48);
- sprintf(buffer,"%d\t %d\t %d ",*score,nf,diamonds);
- (void) addstr(buffer);
- if(!debug_disp)
- display(sx,sy,frow,*score);
- else
- map(frow);
- deadyet = fall(&mx,&my,nx,ny,sx,sy,howdead);
- if(deadyet == 0)
- deadyet = fall(&mx,&my,lx,ly,sx,sy,howdead);
- if(deadyet == 0)
- deadyet = fall(&mx,&my,lx+1,ly-1,sx,sy,howdead);
- if(deadyet == 0)
- deadyet = fall(&mx,&my,lx+1,ly+1,sx,sy,howdead);
- if(deadyet == 0)
- deadyet = fall(&mx,&my,lx-1,ly+1,sx,sy,howdead);
- if(deadyet == 0)
- deadyet = fall(&mx,&my,lx-1,ly-1,sx,sy,howdead);
- move(16,0);
- refresh();
- }
- else
- {
- screen[ny][nx] = ' ';
- printf("Teleport out of order");
- }
- break;
- case 'M':
- strcpy(howdead,"a hungry monster");
- deadyet = 1;
- if(!debug_disp)
- draw_symbol((x-sx+5)*3,(y-sy+3)*2,' ');
- else
- {
- move(y+1,x+1);
- addch(' ');
- }
- move(16,0);
- refresh();
- break;
- case 'S':
- strcpy(howdead,"walking into a monster");
- deadyet = 1;
- if(!debug_disp)
- draw_symbol((x-sx+5)*3,(y-sy+3)*2,' ');
- else
- {
- move(y+1,x+1);
- addch(' ');
- }
- move(16,0);
- refresh();
- break;
- default:
- break;
- }
- if((y == ny) && (x == nx) && (maxmoves>0))
- {
- (void) sprintf(buffer,"Moves remaining = %d ",--maxmoves);
- move(15,48);
- (void) addstr(buffer);
- }
- if(maxmoves == 0)
- {
- strcpy(howdead,"running out of time");
- return(howdead);
- }
- if(!debug_disp)
- {
- if ((x<(sx-3))&& (deadyet ==0)) /* screen scrolling if necessary */
- {
- sx-=6;
- if(sx < 4)
- sx = 4;
- display(sx,sy,frow,*score);
- }
- if ((y<(sy-2))&& (deadyet == 0))
- {
- sy-=5;
- if(sy < 2)
- sy = 2;
- display(sx,sy,frow,*score);
- }
- if ((x>(sx+3)) && (deadyet == 0))
- {
- sx+=6;
- if(sx>(ROWLEN -5))
- sx = ROWLEN -5;
- display(sx,sy,frow,*score);
- }
- if ((y>(sy+2))&& (deadyet ==0))
- {
- sy+=5;
- if(sy > (NOOFROWS-3))
- sy = NOOFROWS -3;
- display(sx,sy,frow,*score);
- }
- }
-
- /* MONSTER SECTION */
-
- /* big monster first */
- if(mx == -2) /* has the monster been killed ? */
- {
- *score+=100;
- mx = my = -1;
- move(3,48);
- sprintf(buffer,"%d\t %d\t",*score,nf);
- (void) addstr(buffer);
- draw_symbol(48,10,' ');
- move(16,0);
- refresh();
- } /* if monster still alive */
- if(mx != -1) /* then move that monster ! */
- {
- screen[my][mx] = ' ';
- if(mx>x)
- xdirection = -1;
- else
- xdirection = 1;
- if(!debug_disp)
- {
- if((my<(sy+4))&&(my>(sy-4))&&(mx<(sx+6))&&(mx>(sx-6)))
- draw_symbol((mx-sx+5)*3,(my-sy+3)*2,' ');
- }
- else
- {
- move(my+1,mx+1);
- addch(' ');
- }
- if((hd = (mx-x))<0)
- hd = -hd;
- if((vd = (my-y))<0)
- vd = -vd;
- if((hd>vd)&&((screen[my][mx+xdirection] == ' ')||(screen[my][mx+xdirection] == '@')))
- mx+=xdirection;
- else
- {
- if(my>y)
- ydirection = -1;
- else
- ydirection = 1;
- if((screen[my+ydirection][mx] == ' ')||(screen[my+ydirection][mx] == '@'))
- my+=ydirection;
- else
- if((screen[my][mx+xdirection] == ' ')||(screen[my][mx+xdirection] == '@'))
- mx+=xdirection;
- }
- if(!debug_disp)
- {
- if((my<(sy+4))&&(my>(sy-4))&&(mx<(sx+6))&&(mx>(sx-6)))
- draw_symbol((mx-sx+5)*3,(my-sy+3)*2,'M');
- }
- else
- {
- move(my+1,mx+1);
- addch('M');
- }
- if(screen[my][mx] == '@') /* ha! gottim! */
- {
- strcpy(howdead,"a hungry monster");
- move(16,0);
- refresh();
- return(howdead);
- }
- screen[my][mx] = 'M';
- move(16,0);
- refresh();
- }
-
- current = &start_of_list;
- while((current != tail_of_list)&&(!deadyet))
- /* deal with those little monsters */
- {
- monster = current->next;
- new_disp = new_direction( monster->x, monster->y, monster->mx, monster->my );
- if(monster->under!='S')
- {
- screen[monster->y][monster->x] = monster->under;
- if(!debug_disp)
- {
- if((monster->y < (sy+4)) && (monster->y > (sy-4)) && (monster->x < (sx+6)) && (monster->x > (sx-6)))
- draw_symbol((monster->x-sx+5)*3,(monster->y-sy+3)*2,monster->under);
- }
- else
- {
- move(monster->y+1,monster->x+1);
- addch(monster->under);
- }
- if(monster->under == ' ')
- deadyet+=check(&mx,&my,monster->x,monster->y,new_disp.d[0],new_disp.d[1],sx,sy,howdead);
- }
- else
- monster->under=' ';
- monster->mx = new_disp.d[0];
- monster->my = new_disp.d[1];
- monster->x += monster->mx;
- monster->y += monster->my;
- monster->under = screen[monster->y][monster->x];
- screen[monster->y][monster->x] = 'S'; /* move into new space */
- if(!debug_disp)
- {
- if((monster->y < (sy+4)) && (monster->y > (sy-4)) && (monster->x < (sx+6)) && (monster->x > (sx-6)))
- draw_symbol((monster->x-sx+5)*3,(monster->y-sy+3)*2,'S');
- }
- else
- {
- move(monster->y+1,monster->x+1);
- addch('S');
- }
- if(monster->under == '@') /* monster hit you? */
- {
- strcpy(howdead,"the little monsters");
- move(16,0);
- refresh();
- return(howdead);
- }
- if(monster->under == '+') /* monster hit cage? */
- {
- *score +=20;
- max_score -= 20;
- move(3,48);
- sprintf(buffer,"%d\t %d\t %d ",*score,nf,diamonds);
- (void) addstr(buffer);
- /* remove from chain, and insert at the end (at last_of_list) */
- if(monster == tail_of_list)
- tail_of_list = tail_of_list->prev;
- else
- {
- current->next = monster-> next;
- current->next->prev = current;
- monster->next = NULL;
- monster->prev = last_of_list;
- last_of_list->next = monster;
- last_of_list = monster;
- }
- screen[monster->y][monster->x] = '*';
- if(!debug_disp)
- {
- if((monster->y < (sy+4)) && (monster->y > (sy-4)) && (monster->x < (sx+6)) && (monster->x > (sx-6)))
- draw_symbol((monster->x-sx+5)*3,(monster->y-sy+3)*2,'*');
- }
- else
- {
- move(monster->y+1,monster->x+1);
- addch('*');
- }
- }
- else
- current = monster;
- move(16,0);
- refresh();
- }
-
- if((edit_mode)&&(deadyet)) { /* stop death if testing */
- if(!debug_disp)
- move(18,0);
- else
- move(20,0);
- addstr("You were killed by ");
- addstr(howdead);
- addstr("\nPress 'c' to continue.");
- refresh();
- ch=getch();
- if(ch == 'c')
- deadyet = 0;
- if(!debug_disp)
- move(18,0);
- else
- move(20,0);
- addstr(" ");
- addstr("\n ");
- refresh();
- }
-
- }
- return(howdead);
- }
-